#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2021/4/14 18:51
# @Author  : Grayson Liu
# @Email   : graysonliu@foxmail.com
# @File    : GraphicInputWizardDialog.py
from PyQt5.QtWidgets import QDialog, QFileDialog, QMessageBox

from ui.Ui_GraphicInputWizardDialog import Ui_GraphicInputWizardDialog
from CustomSignal import CustomSignal

import re


class GraphicInputWizardDialog(QDialog, Ui_GraphicInputWizardDialog):
    """
    设置遥感影像输入的对话框
    """
    global_signal = CustomSignal()
    input_type_dic = {
        "WorldView": 0,
        "Planet": 1
    }

    def __init__(self, input_dic: dict, parent=None):
        """
        初始化
        :param input_dic: 从ProjectForm传递而来的输入信息
        :param parent: 父窗体
        """
        super(GraphicInputWizardDialog, self).__init__(parent)
        self.setupUi(self)

        self.num = 0

        # 将ProjectForm传递而来的输出信息显示在当前界面上
        if input_dic:
            self.txtGraphicPath.setText(input_dic["path"])
            self.comboBoxGraphicType.setCurrentIndex(GraphicInputWizardDialog.input_type_dic[input_dic["type"]])
            if input_dic["calculate"] == "single":
                self.rdSingleRaster.setChecked(True)
                self.spinBoxRasterNumber.setValue(input_dic["raster"])
            else:
                self.rdMultipleRaster.setChecked(True)
                self.txtRasterCalculate.setText(input_dic["raster"])

        # TODO: 绑定信号和槽
        self.btnCancel.clicked.connect(lambda: self.close())
        self.btnConfirm.clicked.connect(self.confirm_input)
        self.btnBrowse.clicked.connect(self.browse_file)
        self.btnHelp.clicked.connect(self.show_help)
        self.btnValidate.clicked.connect(self.validate_expression)

    def browse_file(self):
        """
        对话框”浏览“按钮的槽函数
        :return:
        """
        # 打开文件浏览器，选择输入影像的路径
        graphic_path, graphic_type = QFileDialog.getOpenFileName(self, "选择遥感影像文件", filter="GeoTiff Files(*.tif)")
        if graphic_path == "":
            return
        else:
            self.txtGraphicPath.setText(graphic_path)

    def confirm_input(self):
        """
        对话框”确认“按钮的槽函数
        :return:
        """
        input_dic = {
            "path": self.txtGraphicPath.text(),
            "type": self.comboBoxGraphicType.currentText(),
        }
        if self.rdSingleRaster.isChecked():
            raster = self.spinBoxRasterNumber.value()
            input_dic["calculate"] = "single"
            input_dic["raster"] = raster  # 此时为int型
        else:
            raster = self.txtRasterCalculate.text()
            input_dic["calculate"] = "multiple"
            input_dic["raster"] = raster  # 此时为str型

        # 给主窗体发信号，把信息发送给ProjectForm进行处理
        GraphicInputWizardDialog.global_signal.set_input.emit(input_dic)
        self.close()

    def show_help(self):
        """
        点击“输入说明”标签的槽函数，弹出一个MessageBox
        :return:
        """
        help_str = ("这里输入计算相关指数的表达式，程序能自动解析。\n"
                    "运算对象用{X}表示，其中X是波段号，这相当于一个矩阵。 \n"
                    "运算符号支持+，-，*，/，()，也支持数字与矩阵进行运算（例如1.5 * {4}，表示矩阵每一个元素乘1.5），\n"
                    "仅使用小括号，括号必须正确嵌套。\n"
                    "示例：({7} - {5}) / ({7} + {5})，计算NDVI指数的表达式。\n"
                    "输入完成之后请点击“验证“按钮进行检验。\n"
                    )
        QMessageBox.about(self, "输入说明", help_str)

    def validate_expression(self):
        """
        对话框“检验”按钮的槽函数，用于
        :return:
        """

        def convert(matched):
            """
            转换函数，将识别的 {X} 转换为 [X-1,:,:] 的形式，传递给正则表达式替换re.sub()使用
            :param matched:
            :return:
            """
            index = int(matched.group("value")) - 1
            return "{}".format(index)

        try:
            input_str = self.txtRasterCalculate.text()
            eval_str = re.sub("{(?P<value>\d+)}", convert, input_str)
            result = eval(eval_str)
        except:
            QMessageBox.warning(self, "验证结果", "验证不正确，请检查。", QMessageBox.Ok)
        else:
            QMessageBox.information(self, "验证结果", "验证正确，可以进行下一步操作。", QMessageBox.Ok)
